﻿using System;
using System.Collections.Generic;
using Bettzueche.RLLibrary.Types;

namespace Bettzueche.RLLibrary.Functions {
    /// <summary>
    /// Die Erkundungsstrategie gibt an, welche (nächste)Aktion zu wählen ist.
    /// </summary>
    /// <typeparam name="A">Actiontyp, z.B. <see cref="GridAction"/></typeparam>
    /// <typeparam name="R">Struct-Typ der Werte, die zur Entsscheidungsfindung herangezogen werden. Es wird double oder int empfohlen.</typeparam>
    /// <remarks>
    /// Der Methode getAction werden beliebige Basiswerte übergeben, aufgrund derer entschieden wird, welche Aktion zurückgegeben wird.
    /// Normalerweise sind die Parameter Q- oder V-Werte zu den möglichen Aktion. Es wird dann bspw die zu dem besten Wert korrespondierende Aktion gewählt.
    /// </remarks>
    public interface IExplorationPolicy
    {
        /// <summary>
        /// Gibt in Abhängigkeit der spezifizierten Schätzwerte ein Aktion.
        /// </summary>
        /// <param name="estimates">Schätzwerte (normalerweise V- oder Q- Werte)</param>
        /// <returns>Aktion, die aufgrund der Schätzwerte ermittelt wurde</returns>
        IAction GetAction(params double[] estimates);

    }


    /// <summary>
    /// Die Erkundungsstrategie gibt an, welche (nächste)Aktion zu wählen ist.
    /// </summary>
    /// <typeparam name="A">Actiontyp, z.B. <see cref="GridAction"/></typeparam>
    /// <typeparam name="R">Struct-Typ der Werte, die zur Entsscheidungsfindung herangezogen werden. Es wird double oder int empfohlen.</typeparam>
    /// <remarks>
    /// Der Methode getAction werden beliebige Basiswerte übergeben, aufgrund derer entschieden wird, welche Aktion zurückgegeben wird.
    /// Normalerweise sind die Parameter Q- oder V-Werte zu den möglichen Aktion. Es wird dann bspw die zu dem besten Wert korrespondierende Aktion gewählt.
    /// </remarks>
    public abstract class GenericExplorationPolicy<A> : IExplorationPolicy
        where A : IAction
        /*where R : struct*/
    {
        ///// <summary>
        ///// Gibt in Abhängigkeit der spezifizierten Schätzwerte ein Aktion.
        ///// </summary>
        ///// <param name="estimates">Schätzwerte (normalerweise V- oder Q- Werte)</param>
        ///// <returns>Aktion, die aufgrund der Schätzwerte ermittelt wurde</returns>
        //public abstract A GetAction(params R[] estimates);


        /// <summary>
        /// Gibt in Abhängigkeit der spezifizierten Schätzwerte ein Aktion.
        /// </summary>
        /// <param name="estimates">Schätzwerte (normalerweise V- oder Q- Werte)</param>
        /// <returns>
        /// Aktion, die aufgrund der Schätzwerte ermittelt wurde
        /// </returns>
        /// <exception cref="System.NotSupportedException">Generic Typ R ist nicht Double.</exception>
        public abstract A GetAction(params double[] estimates);
    /*
        {
            if (estimates is R[])
                return this.GetAction(estimates);
            throw new NotSupportedException("Generic Typ R ist nicht Double.");
        }*/

        IAction IExplorationPolicy.GetAction(params double[] estimates) {
            return this.GetAction(estimates);
        }
    }

    
}
